package com.adms.service;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.adms.domain.User;
import com.adms.domain.UserExample;
import com.adms.domain.UserExample.Criteria;
import com.adms.domain.UserMapper;
import com.adms.shiro.WechatUsernamePasswordToken;
import com.adms.util.PasswordUtil;
import com.adms.util.ShiroUtil;
import com.adms.util.WechatUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;

@Transactional
@Service
public class UserService {

	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private UserMapper userMapper;

	public User getByUserId(Integer userId) {
		return userMapper.selectByPrimaryKey(userId);
	}

	public User getByPhone(String phone) {
		return userMapper.selectByPhone(phone);
	}

	public User getByOpenid(String openid) {
		return userMapper.selectByOpenid(openid);
	}

	public PageInfo<User> list(User user, String timeField, Date start, Date end, String orderByClause,String key,
			Integer pageNum, Integer pageSize, Integer navigatePages) {

		UserExample ex = constructExample(user, timeField, start, end, orderByClause,key);

		PageHelper.startPage(pageNum, pageSize);
		List<User> users = userMapper.selectByExample(ex);
		return new PageInfo<>(users, navigatePages);
	}

	private UserExample constructExample(User user, String timeField, Date start, Date end,
			String orderByClause,String key) {
		UserExample ex = new UserExample();
		Criteria or = ex.or();
		if (user != null) {
			Integer sex = user.getSex();
			String role = user.getRole();
			Boolean isLocked = user.getIsLocked();
			Integer auditState = user.getAuditState();
			if (sex != null) {
				or.andSexEqualTo(sex);
			}
			if (role != null) {
				or.andRoleEqualTo(role);
			}
			if (isLocked != null) {
				or.andIsLockedEqualTo(isLocked);
			}
			if (auditState != null) {
				or.andAuditStateEqualTo(auditState);
			}
		}

		if (StringUtil.isNotEmpty(timeField)) {
			if (timeField.equals("createTime")) {
				if (start != null) {
					if (end != null) {
						or.andCreateTimeBetween(start, end);
					} else {
						or.andCreateTimeGreaterThanOrEqualTo(start);
					}
				} else {
					if (end != null) {
						or.andCreateTimeLessThanOrEqualTo(end);
					}
				}
			}
			if (timeField.equals("updateTime")) {
				if (start != null) {
					if (end != null) {
						or.andUpdateTimeBetween(start, end);
					} else {
						or.andUpdateTimeGreaterThanOrEqualTo(start);
					}
				} else {
					if (end != null) {
						or.andUpdateTimeLessThanOrEqualTo(end);
					}
				}
			}
			if (timeField.equals("lastTime")) {
				if (start != null) {
					if (end != null) {
						or.andLastTimeBetween(start, end);
					} else {
						or.andLastTimeGreaterThanOrEqualTo(start);
					}
				} else {
					if (end != null) {
						or.andLastTimeLessThanOrEqualTo(end);
					}
				}
			}
		}

		if (StringUtil.isNotEmpty(orderByClause)) {
			ex.setOrderByClause(orderByClause);
		} else {
			ex.setOrderByClause("user.create_time desc");
		}
		//目前关键字key仅仅匹配用户名
		if(StringUtil.isNotEmpty(key)) {
			or.andUsernameLike("%"+key+"%");
		}

		return ex;
	}

	public User login(String phone, String password, boolean rememberMe) {
		UsernamePasswordToken token = new UsernamePasswordToken(phone, password, rememberMe);
		Subject subject = SecurityUtils.getSubject();
		subject.login(token);
		User loginUser = (User) subject.getSession().getAttribute("user");
		//修改最后一次登录时间
		loginUser.setLastTime(new Date());
		userMapper.updateByPrimaryKey(loginUser);
		return loginUser;
	}
	

	public boolean logout() {
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return true;
	}

	public Map<String, Object> wechatLogin(String code) {
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession();
		Map<String, Object> result = new HashMap<>();
		result.put(ShiroHttpSession.DEFAULT_SESSION_ID_NAME, session.getId());
		String url = MessageFormat.format(WechatUtil.CODE2SESSION, code);
		try {
			URLConnection connection = new URL(url).openConnection();
			InputStream inputStream = connection.getInputStream();
			Map<?, ?> value = objectMapper.readValue(inputStream, Map.class);
			if (value.get("errcode") == null) {
				String openid = (String) value.get("openid");
				String session_key = (String) value.get("session_key");
				System.out.println("----------------------------------->"+openid);
				System.out.println("+++++++++++++++++++++>"+session_key);
				session.setAttribute("openid", openid);
				session.setAttribute("session_key", session_key);
				User existUser = getByOpenid(openid);
				result.put("user", existUser);
				if (existUser != null) {
					session.setAttribute("user", existUser);
					subject.login(new WechatUsernamePasswordToken());
					//修改最后一次登录时间
					existUser.setLastTime(new Date());
					userMapper.updateByPrimaryKey(existUser);
					result.put("isBound", true);
				} else {
					result.put("isBound", false);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public User wechatBind(String phone, Integer sex, String headImage) {
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession();
		String openid = (String) session.getAttribute("openid");

		User existUser = getByPhone(phone);
		existUser.setOpenid(openid);
		existUser.setSex(sex);
		existUser.setHeadImage(headImage);
		existUser.setLastTime(new Date());
		userMapper.updateByPrimaryKey(existUser);

		session.setAttribute("user", existUser);
		subject.login(new WechatUsernamePasswordToken());

		return existUser;
	}

	public boolean checkPhone(String phone) {
		UserExample ex = new UserExample();
		ex.or().andPhoneEqualTo(phone);
		return userMapper.countByExample(ex) == 0;
	}

	public boolean create(User user) {
		User loginUser = ShiroUtil.getUser();
		user.setRefUserId(loginUser.getUserId());
		user.setPassword(user.getPhone().substring(3));
		PasswordUtil.encryptPassword(user);
		userMapper.insertSelective(user);
		return true;
	}

	public boolean createByFile(MultipartFile file) {
		// TODO Auto-generated method stub
		return true;
	}

	public boolean update(User user) {
		userMapper.updateByPrimaryKeySelective(user);
		return true;
	}

	public boolean delete(int[] userIds) {
		if (userIds != null) {
			int length = userIds.length;
			if (length != 0) {
				if (length == 1) {
					userMapper.deleteByPrimaryKey(userIds[0]);
				} else if (length > 1) {
					userMapper.deleteBatch(userIds);
				}
			}
		}
		return true;
	}

	public boolean checkPassword(String password) {
		return PasswordUtil.checkPassword(password,ShiroUtil.getUser());
	}

	public boolean resetPassword(String phone, String password) {
		if(StringUtil.isNotEmpty(phone)) {
			User user = new User();
			user.setPhone(phone);
			user.setPassword(password);
			PasswordUtil.encryptPassword(user);
			UserExample ex = new UserExample();
			Criteria or = ex.or();
			or.andPhoneEqualTo(phone);
			userMapper.updateByExampleSelective(user, ex);
		}else {
			User loginUser = ShiroUtil.getUser();
			if(loginUser != null) {
				loginUser.setPassword(password);
				PasswordUtil.encryptPassword(loginUser);
				userMapper.updateByPrimaryKeySelective(loginUser);
				SecurityUtils.getSubject().logout();
			}
		}
		return true;
	}

	public List<User> getTransferUsers(Integer siteId,Integer gridUserId,Integer handleUserId) {
		User loginUser = ShiroUtil.getUser();
		Integer loginUserId = loginUser.getUserId();
		List<User> users = null;
		if(loginUserId == gridUserId) {
			users = userMapper.selectTransferGridUsersBySiteId(siteId);
		}else if(loginUserId == handleUserId) {
			users = userMapper.selectTransferHandleUsersBySiteId(siteId);
		}
		return users;
	}

	public List<User> getSiteRelativeUsers(Integer siteId) {
		return userMapper.selectRelativeUsersBySiteId(siteId);
	}

	public List<User> getDefaultGridUsers() {
		return userMapper.selectDefaultGridUsers();
	}
}
